package simpledb;

import java.io.IOException;

/**
 * The delete operator. Delete reads tuples from its child operator and removes
 * them from the table they belong to.
 * 执行删除操作的类
 * 给定一个元组迭代器，TransactionId标记操作页面为dirty
 * fetchNext()中调用HeapFile中的delete()操作，逐个删除迭代器中每个元组
 */
public class Delete extends Operator {

    private static final long serialVersionUID = 1L;

    private TransactionId tid;
    private OpIterator child;
    private TupleDesc tupleDesc;
    //表明该Delete操作是否被使用，默认为false,只有第一次使用生效，后面返回null
    private boolean hasAccessed;

    /**
     * Constructor specifying the transaction that this delete belongs to as
     * well as the child to read from.
     * 
     * @param t
     *            The transaction this delete runs in
     * @param child
     *            The child operator from which to read tuples for deletion
     */
    public Delete(TransactionId t, OpIterator child) {
        // some code goes here
        this.tid = t;
        this.child = child;
        this.tupleDesc = new TupleDesc(new Type[]{Type.INT_TYPE},new String[]{null});
        this.hasAccessed = false;
    }

    public TupleDesc getTupleDesc() {
        // some code goes here
        return tupleDesc;
    }

    public void open() throws DbException, TransactionAbortedException {
        // some code goes here
        super.open();
        child.open();
    }

    public void close() {
        // some code goes here
        child.close();
    }

    public void rewind() throws DbException, TransactionAbortedException {
        // some code goes here
        child.rewind();

    }

    /**
     * Deletes tuples as they are read from the child operator. Deletes are
     * processed via the buffer pool (which can be accessed via the
     * Database.getBufferPool() method.
     * 
     * @return A 1-field tuple containing the number of deleted records.
     * @see Database#getBufferPool
     * @see BufferPool#deleteTuple
     * fetch()完成迭代器中所有元组的删除
     * 返回删除的行数
     */
    protected Tuple fetchNext() throws TransactionAbortedException, DbException {
        // some code goes here
        if(hasAccessed)
            return null;
        int deleterows = 0;
        while(child.hasNext())
        {
            Tuple tuple = child.next();
            try {
                Database.getBufferPool().deleteTuple(tid,tuple);
            } catch (IOException e) {
                e.printStackTrace();
            }
            deleterows++;
        }
        Tuple return_tup = new Tuple(tupleDesc);
        return_tup.setField(0,new IntField(deleterows));
        hasAccessed = true;
        return return_tup;
    }

    @Override
    public OpIterator[] getChildren() {
        // some code goes here
        return new OpIterator[]{child};
    }

    @Override
    public void setChildren(OpIterator[] children) {
        child = children[0];
        // some code goes here
    }

}
